//@version=6
// © The_lurker Fawaz Al-Enezi فواز العنزي

indicator("Smart Adaptive Double Patterns [The_lurker]", shorttitle="SADP [The_lurker]", overlay=true, max_lines_count=500, max_labels_count=500, max_boxes_count=500, max_bars_back=2000)

// ═══════════════════════════════════════════════════════════════════
// 📌 القسم الأول: إعدادات الإدخال
// ═══════════════════════════════════════════════════════════════════

// ✅ 1. اللغة والإعدادات العامة
i_language = input.string("عربي | Arabic", "اللغة | Language", options=["عربي | Arabic", "English | إنجليزي"], group="⚙️ General | الإعدادات العامة")
i_show_old_patterns = input.bool(false, "إظهار النماذج السابقة | Show Previous Patterns", group="⚙️ General | الإعدادات العامة")

// ✅ 2. تفعيل النماذج
i_enable_double_bottom = input.bool(true, "✅ تفعيل القاع المزدوج | Enable Double Bottom", group="🔘 Pattern Selection | اختيار النماذج")
i_enable_double_top = input.bool(true, "✅ تفعيل القمة المزدوجة | Enable Double Top", group="🔘 Pattern Selection | اختيار النماذج")

// ✅ 3. كشف النموذج
left_len = input.int(5, "شموع اليسار | Pivots Left", minval=1, group="🔍 Pattern Detection | كشف النموذج")
right_len = input.int(3, "شموع اليمين | Pivots Right", minval=1, group="🔍 Pattern Detection | كشف النموذج")
min_distance = input.int(10, "الحد الأدنى بين النقطتين | Min Width", minval=5, group="🔍 Pattern Detection | كشف النموذج")
tolerance_pct = input.float(1.5, "نسبة التماثل % | Tolerance", minval=0.1, step=0.1, group="🔍 Pattern Detection | كشف النموذج")
min_arm_len = input.int(10, "الحد الأدنى للذراع | Min Arm", minval=5, group="🔍 Pattern Detection | كشف النموذج")
min_trend_len = input.int(10, "طول المسار | Min Trend", minval=5, group="🔍 Pattern Detection | كشف النموذج")
trend_lookback = input.int(50, "مدى البحث عن المسار | Trend Lookback", group="🔍 Pattern Detection | كشف النموذج")
i_extension_multiplier = input.float(2.0, "معامل التمدد | Extension Multiplier", minval=1.0, maxval=5.0, step=0.5, group="🔍 Pattern Detection | كشف النموذج")

// ✅ 4. تقييم الجودة
i_min_quality = input.int(60, "الحد الأدنى للجودة | Min Quality Score", minval=0, maxval=100, group="⭐ Quality Scoring | تقييم الجودة")
i_symmetry_weight = input.float(30.0, "وزن التماثل | Symmetry Weight", minval=0, maxval=50, step=5, group="⭐ Quality Scoring | تقييم الجودة")
i_trend_weight = input.float(20.0, "وزن الاتجاه | Trend Weight", minval=0, maxval=50, step=5, group="⭐ Quality Scoring | تقييم الجودة")
i_volume_weight = input.float(20.0, "وزن الحجم | Volume Weight", minval=0, maxval=50, step=5, group="⭐ Quality Scoring | تقييم الجودة")
i_depth_weight = input.float(15.0, "وزن العمق | Depth Weight", minval=0, maxval=50, step=5, group="⭐ Quality Scoring | تقييم الجودة")
i_structure_weight = input.float(15.0, "وزن الهيكل | Structure Weight", minval=0, maxval=50, step=5, group="⭐ Quality Scoring | تقييم الجودة")

// ✅ 5. الفلاتر
i_use_atr_filter = input.bool(true, "تفعيل فلتر التقلب | ATR Filter", group="🔧 Filters | الفلاتر")
i_atr_period = input.int(14, "فترة ATR | ATR Period", minval=5, maxval=50, group="🔧 Filters | الفلاتر")
i_use_adx_filter = input.bool(true, "تفعيل فلتر الاتجاه | ADX Filter", group="🔧 Filters | الفلاتر")
i_adx_period = input.int(14, "فترة ADX | ADX Period", minval=5, maxval=50, group="🔧 Filters | الفلاتر")
i_adx_threshold = input.float(20.0, "حد ADX | ADX Threshold", minval=10, maxval=50, step=5, group="🔧 Filters | الفلاتر")
i_use_volume_filter = input.bool(true, "تفعيل فلتر الحجم | Volume Filter", group="🔧 Filters | الفلاتر")
i_volume_period = input.int(20, "فترة متوسط الحجم | Volume MA", minval=5, maxval=100, group="🔧 Filters | الفلاتر")

// ✅ 6. الأهداف - القاع المزدوج
i_bottom_target_bullish = input.string("متوازن | Balanced", "🎯 هدف القاع الصاعد | Bottom Bullish Target", options=["محافظ | Conservative", "متوازن | Balanced", "عدواني | Aggressive"], group="🎯 Targets | الأهداف")
i_bottom_target_bearish = input.string("محافظ | Conservative", "📉 هدف القاع الهابط | Bottom Bearish Target", options=["محافظ | Conservative", "متوازن | Balanced", "عدواني | Aggressive"], group="🎯 Targets | الأهداف")

// ✅ 7. الأهداف - القمة المزدوجة
i_top_target_bearish = input.string("متوازن | Balanced", "📉 هدف القمة الهابط | Top Bearish Target", options=["محافظ | Conservative", "متوازن | Balanced", "عدواني | Aggressive"], group="🎯 Targets | الأهداف")
i_top_target_bullish = input.string("محافظ | Conservative", "🎯 هدف القمة الصاعد | Top Bullish Target", options=["محافظ | Conservative", "متوازن | Balanced", "عدواني | Aggressive"], group="🎯 Targets | الأهداف")

// ✅ 8. العرض البصري
i_label_size = input.string("صغير | Small", "حجم العلامات | Label Size", options=["صغير | Small", "عادي | Normal", "كبير | Large", "ضخم | Huge"], group="🎨 Visual | العرض البصري")

i_bottom_text_color = input.color(color.new(#2962FF, 0), "لون نص القاع | Bottom Text Color", group="🎨 Visual | العرض البصري")
i_bottom_bg_color = input.color(color.new(#FFC107, 80), "خلفية Bottom | Bottom Background", group="🎨 Visual | العرض البصري")
i_bottom_color_high = input.color(color.new(#00BCD4, 0), "القاع - جودة عالية | Bottom High Quality", group="🎨 Visual | العرض البصري")
i_bottom_color_med = input.color(color.new(#FFC107, 0), "القاع - جودة متوسطة | Bottom Medium Quality", group="🎨 Visual | العرض البصري")
i_bottom_color_low = input.color(color.new(#9E9E9E, 0), "القاع - جودة منخفضة | Bottom Low Quality", group="🎨 Visual | العرض البصري")

i_top_text_color = input.color(color.new(#FF1744, 0), "لون نص القمة | Top Text Color", group="🎨 Visual | العرض البصري")
i_top_bg_color = input.color(color.new(#FF1744, 80), "خلفية Top | Top Background", group="🎨 Visual | العرض البصري")
i_top_color_high = input.color(color.new(#FF5252, 0), "القمة - جودة عالية | Top High Quality", group="🎨 Visual | العرض البصري")
i_top_color_med = input.color(color.new(#FFC107, 0), "القمة - جودة متوسطة | Top Medium Quality", group="🎨 Visual | العرض البصري")
i_top_color_low = input.color(color.new(#9E9E9E, 0), "القمة - جودة منخفضة | Top Low Quality", group="🎨 Visual | العرض البصري")

i_target_achieved_color = input.color(color.new(#4CAF50, 0), "لون تحقق الهدف | Target Achieved Color", group="🎨 Visual | العرض البصري")
i_bearish_reversal_color = input.color(color.new(#FF1744, 0), "لون الانعكاس الهبوطي | Bearish Reversal", group="🎨 Visual | العرض البصري")
i_bullish_reversal_color = input.color(color.new(#00BCD4, 0), "لون الانعكاس الصعودي | Bullish Reversal", group="🎨 Visual | العرض البصري")

i_fill_transparency = input.int(85, "شفافية التضليل | Fill Transparency", minval=70, maxval=95, group="🎨 Visual | العرض البصري")
i_show_info_table = input.bool(true, "عرض جدول المعلومات | Show Info Table", group="🎨 Visual | العرض البصري")
i_table_size = input.string("عادي | Normal", "حجم الجدول | Table Size", options=["صغير | Small", "عادي | Normal", "كبير | Large"], group="🎨 Visual | العرض البصري")
i_table_position = input.string("أعلى يمين | Top Right", "موضع الجدول | Table Position", options=["أعلى يمين | Top Right", "أعلى يسار | Top Left", "أسفل يمين | Bottom Right", "أسفل يسار | Bottom Left"], group="🎨 Visual | العرض البصري")

// ═══════════════════════════════════════════════════════════════════
// 📌 دوال مساعدة
// ═══════════════════════════════════════════════════════════════════

get_text(key) =>
    is_arabic = (i_language == "عربي | Arabic")
    switch key
        "smart_double_bottom" => is_arabic ? "قاع مزدوج ذكي" : "Smart Double Bottom"
        "smart_double_top" => is_arabic ? "قمة مزدوجة ذكية" : "Smart Double Top"
        "quality_score" => is_arabic ? "📊 درجة الجودة" : "📊 Quality Score"
        "grade" => is_arabic ? "⭐ التقييم" : "⭐ Grade"
        "target_mode" => is_arabic ? "🎯 نمط الهدف" : "🎯 Target Mode"
        "target_price" => is_arabic ? "🎯 سعر الهدف" : "🎯 Target Price"
        "excellent" => is_arabic ? "⭐ ممتاز" : "⭐ Excellent"
        "very_good" => is_arabic ? "✨ جيد جداً" : "✨ Very Good"
        "good" => is_arabic ? "✓ جيد" : "✓ Good"
        "acceptable" => is_arabic ? "○ مقبول" : "○ Acceptable"
        "bottom_failed" => is_arabic ? "⚠ فشل القاع - هبوطي" : "⚠ Bottom Failed - Bearish"
        "top_failed" => is_arabic ? "⚠ فشل القمة - صاعد" : "⚠ Top Failed - Bullish"
        "status" => is_arabic ? "💡 الحالة" : "💡 Status"
        "reversal_downward" => is_arabic ? "انعكاس هبوطي" : "Reversal Downward"
        "reversal_upward" => is_arabic ? "انعكاس صاعد" : "Reversal Upward"
        "bullish_breakout" => is_arabic ? "اختراق صاعد" : "Bullish Breakout"
        "bearish_breakout" => is_arabic ? "اختراق هابط" : "Bearish Breakout"
        "target" => is_arabic ? "الهدف" : "Target"
        "target_down" => is_arabic ? "الهدف ↓" : "Target ↓"
        "target_up" => is_arabic ? "الهدف ↑" : "Target ↑"
        "bottom1" => is_arabic ? "Bottom 1" : "Bottom 1"
        "bottom2" => is_arabic ? "Bottom 2" : "Bottom 2"
        "top1" => is_arabic ? "Top 1" : "Top 1"
        "top2" => is_arabic ? "Top 2" : "Top 2"
        "conservative" => is_arabic ? "محافظ" : "Conservative"
        "balanced" => is_arabic ? "متوازن" : "Balanced"
        "aggressive" => is_arabic ? "عدواني" : "Aggressive"
        => ""

get_label_size() =>
    (i_label_size == "صغير | Small") ? size.small : (i_label_size == "عادي | Normal") ? size.normal : (i_label_size == "كبير | Large") ? size.large : size.huge

get_bottom_quality_color(quality_score) =>
    (quality_score >= 80) ? i_bottom_color_high : (quality_score >= 60) ? i_bottom_color_med : i_bottom_color_low

get_top_quality_color(quality_score) =>
    (quality_score >= 80) ? i_top_color_high : (quality_score >= 60) ? i_top_color_med : i_top_color_low

get_table_position() =>
    (i_table_position == "أعلى يمين | Top Right") ? position.top_right : (i_table_position == "أعلى يسار | Top Left") ? position.top_left : (i_table_position == "أسفل يمين | Bottom Right") ? position.bottom_right : position.bottom_left

get_text_size() =>
    (i_table_size == "صغير | Small") ? size.tiny : (i_table_size == "عادي | Normal") ? size.small : size.normal

mode_to_text(mode) =>
    (mode == "محافظ | Conservative") ? get_text("conservative") : (mode == "متوازن | Balanced") ? get_text("balanced") : get_text("aggressive")

atr_value = ta.atr(i_atr_period)
[diPlus, diMinus, adx_value] = ta.dmi(i_adx_period, i_adx_period)
volume_ma = ta.sma(volume, i_volume_period)

// ═══════════════════════════════════════════════════════════════════
// 📌 دوال حساب الجودة والأهداف
// ═══════════════════════════════════════════════════════════════════

calculate_bottom_quality(p1_price, p2_price, p3_price, p4_price, p2_idx, p4_idx) =>
    float total_score = 0.0
    float price_diff = math.abs(p2_price - p4_price)
    float avg_bottom = (p2_price + p4_price) / 2
    float symmetry_pct = (price_diff / avg_bottom) * 100
    float symmetry_score = (symmetry_pct <= tolerance_pct) ? (i_symmetry_weight * (1 - (symmetry_pct / tolerance_pct))) : 0.0
    total_score += symmetry_score
    float trend_score = i_use_adx_filter ? ((adx_value >= i_adx_threshold and diMinus > diPlus) ? i_trend_weight : i_trend_weight * 0.3) : i_trend_weight * 0.5
    total_score += trend_score
    float volume_score = 0.0
    if i_use_volume_filter
        int lookback_p4 = bar_index - p4_idx
        int lookback_p2 = bar_index - p2_idx
        if lookback_p4 <= 5000 and lookback_p2 <= 5000
            float vol_p4 = volume[lookback_p4]
            float vol_p2 = volume[lookback_p2]
            float avg_vol = (vol_p4 + vol_p2) / 2
            float volume_ratio = (volume_ma > 0) ? (avg_vol / volume_ma) : 1.0
            volume_score := (volume_ratio < 1.0) ? (i_volume_weight * (1.0 - volume_ratio)) : (i_volume_weight * 0.3)
        else
            volume_score := i_volume_weight * 0.5
    else
        volume_score := i_volume_weight * 0.5
    total_score += volume_score
    float pattern_depth = (p3_price > p4_price) ? ((p3_price - p4_price) / p3_price) : 0.0
    float depth_score = i_depth_weight * math.min(pattern_depth * 10, 1.0)
    total_score += depth_score
    float downtrend_quality = (p1_price > p3_price) ? 1.0 : 0.5
    float peak_position = ((p3_price - p4_price) / (p1_price - p4_price))
    float structure_score = i_structure_weight * downtrend_quality * math.min(peak_position * 2, 1.0)
    total_score += structure_score
    math.min(total_score, 100.0)

calculate_top_quality(p1_price, p2_price, p3_price, p4_price, p2_idx, p4_idx) =>
    float total_score = 0.0
    float price_diff = math.abs(p2_price - p4_price)
    float avg_top = (p2_price + p4_price) / 2
    float symmetry_pct = (price_diff / avg_top) * 100
    float symmetry_score = (symmetry_pct <= tolerance_pct) ? (i_symmetry_weight * (1 - (symmetry_pct / tolerance_pct))) : 0.0
    total_score += symmetry_score
    float trend_score = i_use_adx_filter ? ((adx_value >= i_adx_threshold and diPlus > diMinus) ? i_trend_weight : i_trend_weight * 0.3) : i_trend_weight * 0.5
    total_score += trend_score
    float volume_score = 0.0
    if i_use_volume_filter
        int lookback_p4 = bar_index - p4_idx
        int lookback_p2 = bar_index - p2_idx
        if lookback_p4 <= 5000 and lookback_p2 <= 5000
            float vol_p4 = volume[lookback_p4]
            float vol_p2 = volume[lookback_p2]
            float avg_vol = (vol_p4 + vol_p2) / 2
            float volume_ratio = (volume_ma > 0) ? (avg_vol / volume_ma) : 1.0
            volume_score := (volume_ratio < 1.0) ? (i_volume_weight * (1.0 - volume_ratio)) : (i_volume_weight * 0.3)
        else
            volume_score := i_volume_weight * 0.5
    else
        volume_score := i_volume_weight * 0.5
    total_score += volume_score
    float pattern_depth = (p2_price > p3_price) ? ((p2_price - p3_price) / p2_price) : 0.0
    float depth_score = i_depth_weight * math.min(pattern_depth * 10, 1.0)
    total_score += depth_score
    float uptrend_quality = (p2_price > p1_price) ? 1.0 : 0.5
    float valley_position = ((p2_price - p3_price) / (p2_price - p1_price))
    float structure_score = i_structure_weight * uptrend_quality * math.min(valley_position * 2, 1.0)
    total_score += structure_score
    math.min(total_score, 100.0)

calculate_bottom_bullish_targets(p3_price, p4_price, quality_score) =>
    float height = p3_price - p4_price
    float quality_factor = math.max(quality_score / 100.0, 0.5)
    float t1 = p3_price + (height * 0.618 * quality_factor)
    float t2 = p3_price + (height * 1.0 * quality_factor)
    float t3 = p3_price + (height * 1.618 * quality_factor)
    [t1, t2, t3]

calculate_bottom_bearish_targets(p2_price, p3_price, p4_price) =>
    float min_bottom = math.min(p2_price, p4_price)
    float height = p3_price - min_bottom
    float bt1 = min_bottom - (height * 0.618)
    float bt2 = min_bottom - (height * 1.0)
    float bt3 = min_bottom - (height * 1.618)
    [bt1, bt2, bt3]

calculate_top_bearish_targets(p3_price, p4_price, quality_score) =>
    float height = p4_price - p3_price
    float quality_factor = math.max(quality_score / 100.0, 0.5)
    float t1 = p3_price - (height * 0.618 * quality_factor)
    float t2 = p3_price - (height * 1.0 * quality_factor)
    float t3 = p3_price - (height * 1.618 * quality_factor)
    [t1, t2, t3]

calculate_top_bullish_targets(p2_price, p3_price, p4_price) =>
    float max_top = math.max(p2_price, p4_price)
    float height = max_top - p3_price
    float bt1 = max_top + (height * 0.618)
    float bt2 = max_top + (height * 1.0)
    float bt3 = max_top + (height * 1.618)
    [bt1, bt2, bt3]

// ═══════════════════════════════════════════════════════════════════
// 📌 متغيرات القاع المزدوج
// ═══════════════════════════════════════════════════════════════════

var float[] lows_price = array.new_float()
var int[] lows_idx = array.new_int()

var float bot_p1_price = na
var int bot_p1_idx = na
var float bot_p2_price = na
var int bot_p2_idx = na
var float bot_p3_price = na
var int bot_p3_idx = na
var float bot_p4_price = na
var int bot_p4_idx = na
var float bot_quality_score = na
var color bot_pattern_color = na
var line bot_neckline_left = na
var line bot_neckline_right = na
var line bot_l12 = na
var line bot_l23 = na
var line bot_l34 = na
var line bot_l45 = na
var linefill bot_fill_left = na
var linefill bot_fill_23 = na
var linefill bot_fill_34 = na
var linefill bot_fill_45 = na
var label bot_label1 = na
var label bot_label2 = na
var label bot_label3 = na
var label bot_label4 = na
var label bot_label5 = na
var label bot_labelX = na
var bool bot_breakout = false
var int bot_breakout_bar = na
var float bot_target_price = na
var line bot_target_vline = na
var line bot_target_hline = na
var label bot_target_label = na
var bool bot_target_achieved = false
var int bot_target_achieved_bar = na
var int bot_pattern_width = na
var int bot_max_wait_bars = na
var bool bot_invalidated = false
var int bot_pattern_start_bar = na
var bool bot_bearish_break = false
var int bot_bearish_bar = na
var float bot_bearish_target = na
var line bot_bearish_vline = na
var line bot_bearish_hline = na
var label bot_bearish_label = na
var bool bot_bearish_achieved = false
var int bot_bearish_achieved_bar = na

// ═══════════════════════════════════════════════════════════════════
// 📌 متغيرات القمة المزدوجة
// ═══════════════════════════════════════════════════════════════════

var float[] highs_price = array.new_float()
var int[] highs_idx = array.new_int()

var float top_p1_price = na
var int top_p1_idx = na
var float top_p2_price = na
var int top_p2_idx = na
var float top_p3_price = na
var int top_p3_idx = na
var float top_p4_price = na
var int top_p4_idx = na
var float top_quality_score = na
var color top_pattern_color = na
var line top_neckline_left = na
var line top_neckline_right = na
var line top_l12 = na
var line top_l23 = na
var line top_l34 = na
var line top_l45 = na
var linefill top_fill_left = na
var linefill top_fill_23 = na
var linefill top_fill_34 = na
var linefill top_fill_45 = na
var label top_label1 = na
var label top_label2 = na
var label top_label3 = na
var label top_label4 = na
var label top_label5 = na
var label top_labelX = na
var bool top_breakdown = false
var int top_breakdown_bar = na
var float top_target_price = na
var line top_target_vline = na
var line top_target_hline = na
var label top_target_label = na
var bool top_target_achieved = false
var int top_target_achieved_bar = na
var int top_pattern_width = na
var int top_max_wait_bars = na
var bool top_invalidated = false
var int top_pattern_start_bar = na
var bool top_bullish_break = false
var int top_bullish_bar = na
var float top_bullish_target = na
var line top_bullish_vline = na
var line top_bullish_hline = na
var label top_bullish_label = na
var bool top_bullish_achieved = false
var int top_bullish_achieved_bar = na

var table info_table = na

// ═══════════════════════════════════════════════════════════════════
// 📌 كشف القاع المزدوج
// ═══════════════════════════════════════════════════════════════════

if i_enable_double_bottom
    pl = ta.pivotlow(low, left_len, right_len)
    
    if not na(pl)
        p4_price = pl
        p4_idx = bar_index - right_len
        array.push(lows_price, p4_price)
        array.push(lows_idx, p4_idx)
        if array.size(lows_price) > 50
            array.shift(lows_price)
            array.shift(lows_idx)
        
        int size = array.size(lows_price)
        if size >= 2
            for i = size - 2 to 0
                p2_price = array.get(lows_price, i)
                p2_idx = array.get(lows_idx, i)
                dist = p4_idx - p2_idx
                diff = math.abs(p4_price - p2_price)
                match_pct = (diff / math.min(p4_price, p2_price)) * 100
                
                if dist >= min_distance and match_pct <= tolerance_pct
                    highest_h = -1.0
                    p3_idx = -1
                    broken_low = false
                    
                    for k = 1 to (dist - 1)
                        check_idx = p4_idx - k
                        offset = bar_index - check_idx
                        val_high = high[offset]
                        val_low = low[offset]
                        if val_high > highest_h
                            highest_h := val_high
                            p3_idx := check_idx
                        min_bottoms = math.min(p2_price, p4_price)
                        if val_low < min_bottoms
                            broken_low := true
                    
                    p3_price = highest_h
                    
                    if not broken_low and p3_price > p2_price and p3_price > p4_price
                        distance_2_3 = p3_idx - p2_idx
                        distance_3_4 = p4_idx - p3_idx
                        
                        if distance_2_3 >= min_arm_len and distance_3_4 >= min_arm_len
                            p1_price_best = -1.0
                            p1_idx_best = -1
                            found_trend = false
                            
                            for t = min_trend_len to trend_lookback
                                idx_check = p2_idx - t
                                offset_check = bar_index - idx_check
                                if offset_check >= 0 and offset_check <= 5000
                                    val_h = high[offset_check]
                                    if val_h > p3_price and val_h > p1_price_best
                                        p1_price_best := val_h
                                        p1_idx_best := idx_check
                                        found_trend := true
                            
                            if found_trend
                                p1_price = p1_price_best
                                p1_idx = p1_idx_best
                                is_p2_lowest = true
                                
                                for check_idx = p1_idx + 1 to p2_idx - 1
                                    current_offset = bar_index - check_idx
                                    if current_offset <= 5000 and low[current_offset] < p2_price
                                        is_p2_lowest := false
                                        break
                                
                                if is_p2_lowest
                                    bool pass_atr = true
                                    if i_use_atr_filter
                                        float current_atr = atr_value
                                        float avg_atr = ta.sma(atr_value, 50)
                                        if current_atr > avg_atr * 1.8
                                            pass_atr := false
                                    
                                    bool pass_adx = true
                                    if i_use_adx_filter
                                        if adx_value < (i_adx_threshold * 0.7)
                                            pass_adx := false
                                    
                                    float quality_score = calculate_bottom_quality(p1_price, p2_price, p3_price, p4_price, p2_idx, p4_idx)
                                    bool pass_quality = (quality_score >= i_min_quality)
                                    
                                    if pass_atr and pass_adx and pass_quality
                                        if not i_show_old_patterns
                                            if not na(bot_neckline_left)
                                                line.delete(bot_neckline_left)
                                            if not na(bot_neckline_right)
                                                line.delete(bot_neckline_right)
                                            if not na(bot_l12)
                                                line.delete(bot_l12)
                                            if not na(bot_l23)
                                                line.delete(bot_l23)
                                            if not na(bot_l34)
                                                line.delete(bot_l34)
                                            if not na(bot_l45)
                                                line.delete(bot_l45)
                                            if not na(bot_fill_left)
                                                linefill.delete(bot_fill_left)
                                            if not na(bot_fill_23)
                                                linefill.delete(bot_fill_23)
                                            if not na(bot_fill_34)
                                                linefill.delete(bot_fill_34)
                                            if not na(bot_fill_45)
                                                linefill.delete(bot_fill_45)
                                            if not na(bot_label1)
                                                label.delete(bot_label1)
                                            if not na(bot_label2)
                                                label.delete(bot_label2)
                                            if not na(bot_label3)
                                                label.delete(bot_label3)
                                            if not na(bot_label4)
                                                label.delete(bot_label4)
                                            if not na(bot_label5)
                                                label.delete(bot_label5)
                                            if not na(bot_labelX)
                                                label.delete(bot_labelX)
                                            if not na(bot_target_vline)
                                                line.delete(bot_target_vline)
                                            if not na(bot_target_hline)
                                                line.delete(bot_target_hline)
                                            if not na(bot_target_label)
                                                label.delete(bot_target_label)
                                            if not na(bot_bearish_vline)
                                                line.delete(bot_bearish_vline)
                                            if not na(bot_bearish_hline)
                                                line.delete(bot_bearish_hline)
                                            if not na(bot_bearish_label)
                                                label.delete(bot_bearish_label)
                                        
                                        color pattern_color = get_bottom_quality_color(quality_score)
                                        color fill_color = color.new(pattern_color, i_fill_transparency)
                                        string lbl_sz = get_label_size()
                                        
                                        bot_l12 := line.new(p1_idx, p1_price, p2_idx, p2_price, color=pattern_color, width=2, style=line.style_solid)
                                        bot_l23 := line.new(p2_idx, p2_price, p3_idx, p3_price, color=pattern_color, width=2, style=line.style_solid)
                                        bot_l34 := line.new(p3_idx, p3_price, p4_idx, p4_price, color=pattern_color, width=2, style=line.style_solid)
                                        
                                        float slope = (p2_price - p1_price) / (p2_idx - p1_idx)
                                        float neckline_left_price = p3_price
                                        int neckline_left_idx = math.round(p1_idx + ((neckline_left_price - p1_price) / slope))
                                        bot_neckline_left := line.new(neckline_left_idx, p3_price, p3_idx, p3_price, color=pattern_color, width=1, style=line.style_dotted)
                                        
                                        bot_pattern_width := p4_idx - p2_idx
                                        bot_max_wait_bars := math.round(bot_pattern_width * i_extension_multiplier)
                                        bot_pattern_start_bar := p4_idx
                                        int initial_end = math.min(bar_index, p4_idx + bot_max_wait_bars)
                                        bot_neckline_right := line.new(p3_idx, p3_price, initial_end, p3_price, color=pattern_color, width=1, style=line.style_dotted)
                                        
                                        roof_left = line.new(neckline_left_idx, p3_price, p2_idx, p3_price, color=color.new(color.white, 100))
                                        bot_fill_left := linefill.new(bot_l12, roof_left, color=fill_color)
                                        roof_23 = line.new(p2_idx, p3_price, p3_idx, p3_price, color=color.new(color.white, 100))
                                        bot_fill_23 := linefill.new(bot_l23, roof_23, color=fill_color)
                                        roof_34 = line.new(p3_idx, p3_price, p4_idx, p3_price, color=color.new(color.white, 100))
                                        bot_fill_34 := linefill.new(bot_l34, roof_34, color=fill_color)
                                        
                                        bot_label1 := label.new(p1_idx, p1_price, "1", color=color.new(color.white, 100), style=label.style_label_down, textcolor=i_bottom_text_color, size=lbl_sz)
                                        bot_label2 := label.new(p2_idx, p2_price, get_text("bottom1"), color=i_bottom_bg_color, style=label.style_label_up, textcolor=i_bottom_text_color, size=lbl_sz)
                                        bot_label3 := label.new(p3_idx, p3_price, "3", color=color.new(color.white, 100), style=label.style_label_down, textcolor=i_bottom_text_color, size=lbl_sz)
                                        bot_label4 := label.new(p4_idx, p4_price, get_text("bottom2"), color=i_bottom_bg_color, style=label.style_label_up, textcolor=i_bottom_text_color, size=lbl_sz)
                                        
                                        bot_p1_price := p1_price
                                        bot_p1_idx := p1_idx
                                        bot_p2_price := p2_price
                                        bot_p2_idx := p2_idx
                                        bot_p3_price := p3_price
                                        bot_p3_idx := p3_idx
                                        bot_p4_price := p4_price
                                        bot_p4_idx := p4_idx
                                        bot_quality_score := quality_score
                                        bot_pattern_color := pattern_color
                                        bot_breakout := false
                                        bot_target_achieved := false
                                        bot_invalidated := false
                                        bot_bearish_break := false
                                        bot_bearish_achieved := false
                                        bot_bearish_bar := na
                                        bot_bearish_target := na
                                        bot_bearish_achieved_bar := na
                                        break

// تحديث القاع المزدوج
if i_enable_double_bottom and not na(bot_p3_price)
    if not bot_bearish_break and not bot_breakout and not bot_invalidated
        float min_bottom = math.min(bot_p2_price, bot_p4_price)
        if close < min_bottom
            bot_bearish_break := true
            bot_bearish_bar := bar_index
            
            if not na(bot_l12)
                line.set_color(bot_l12, i_bearish_reversal_color)
            if not na(bot_l23)
                line.set_color(bot_l23, i_bearish_reversal_color)
            if not na(bot_l34)
                line.set_color(bot_l34, i_bearish_reversal_color)
            if not na(bot_neckline_left)
                line.set_color(bot_neckline_left, i_bearish_reversal_color)
            if not na(bot_neckline_right)
                line.delete(bot_neckline_right)
            bot_neckline_right := line.new(bot_p3_idx, bot_p3_price, bar_index, bot_p3_price, color=i_bearish_reversal_color, width=1, style=line.style_dotted)
            
            [bt1, bt2, bt3] = calculate_bottom_bearish_targets(bot_p2_price, bot_p3_price, bot_p4_price)
            bot_bearish_target := i_bottom_target_bearish == "محافظ | Conservative" ? bt1 : i_bottom_target_bearish == "متوازن | Balanced" ? bt2 : bt3
            
            string lbl_sz = get_label_size()
            bot_labelX := label.new(bar_index, close, "✖", color=color.new(color.white, 100), style=label.style_label_up, textcolor=i_bearish_reversal_color, size=lbl_sz)
            bot_bearish_vline := line.new(bar_index, close, bar_index, bot_bearish_target, color=i_bearish_reversal_color, width=1, style=line.style_dotted)
            
            if i_show_info_table
                if not na(info_table)
                    table.delete(info_table)
                info_table := table.new(get_table_position(), 2, 5, border_width=2, border_color=i_bearish_reversal_color, frame_width=2, frame_color=i_bearish_reversal_color)
                string txt_size = get_text_size()
                table.cell(info_table, 0, 0, get_text("bottom_failed"), bgcolor=color.new(i_bearish_reversal_color, 10), text_color=color.white, text_size=txt_size, text_halign=text.align_center)
                table.merge_cells(info_table, 0, 0, 1, 0)
                int row = 1
                table.cell(info_table, 0, row, get_text("target_price"), bgcolor=color.new(i_bearish_reversal_color, 80), text_color=color.white, text_size=txt_size, text_halign=text.align_left)
                table.cell(info_table, 1, row, str.tostring(bot_bearish_target, format.mintick), bgcolor=color.new(i_bearish_reversal_color, 90), text_color=i_bearish_reversal_color, text_size=txt_size, text_halign=text.align_right)
                row += 1
                table.cell(info_table, 0, row, get_text("target_mode"), bgcolor=color.new(i_bearish_reversal_color, 85), text_color=color.white, text_size=txt_size, text_halign=text.align_left)
                table.cell(info_table, 1, row, mode_to_text(i_bottom_target_bearish), bgcolor=color.new(i_bearish_reversal_color, 95), text_color=i_bearish_reversal_color, text_size=txt_size, text_halign=text.align_right)
                row += 1
                table.cell(info_table, 0, row, get_text("status"), bgcolor=color.new(i_bearish_reversal_color, 80), text_color=color.white, text_size=txt_size, text_halign=text.align_left)
                table.cell(info_table, 1, row, get_text("reversal_downward"), bgcolor=color.new(i_bearish_reversal_color, 90), text_color=i_bearish_reversal_color, text_size=txt_size, text_halign=text.align_right)
    
    else if not bot_bearish_break and not bot_breakout and not bot_invalidated
        if (bar_index - bot_pattern_start_bar) >= bot_max_wait_bars
            bot_invalidated := true
            if not na(bot_neckline_right)
                line.delete(bot_neckline_right)
            bot_neckline_right := line.new(bot_p3_idx, bot_p3_price, bot_pattern_start_bar + bot_max_wait_bars, bot_p3_price, color=color.new(bot_pattern_color, 50), width=1, style=line.style_dotted)
        else
            if not na(bot_neckline_right)
                line.delete(bot_neckline_right)
            int current_end = math.min(bar_index, bot_pattern_start_bar + bot_max_wait_bars)
            bot_neckline_right := line.new(bot_p3_idx, bot_p3_price, current_end, bot_p3_price, color=bot_pattern_color, width=1, style=line.style_dotted)
    
    if not bot_bearish_break and not bot_breakout and not bot_invalidated
        if close > bot_p3_price
            bot_breakout := true
            bot_breakout_bar := bar_index
            int p5_idx = bar_index
            float p5_price = bot_p3_price
            
            if not na(bot_neckline_right)
                line.delete(bot_neckline_right)
            bot_neckline_right := line.new(bot_p3_idx, bot_p3_price, p5_idx, bot_p3_price, color=bot_pattern_color, width=1, style=line.style_dotted)
            
            bot_l45 := line.new(bot_p4_idx, bot_p4_price, p5_idx, p5_price, color=bot_pattern_color, width=2, style=line.style_solid)
            roof_45 = line.new(bot_p4_idx, bot_p3_price, p5_idx, bot_p3_price, color=color.new(color.white, 100))
            bot_fill_45 := linefill.new(bot_l45, roof_45, color=color.new(bot_pattern_color, i_fill_transparency))
            
            [target1, target2, target3] = calculate_bottom_bullish_targets(bot_p3_price, bot_p4_price, bot_quality_score)
            bot_target_price := i_bottom_target_bullish == "محافظ | Conservative" ? target1 : i_bottom_target_bullish == "متوازن | Balanced" ? target2 : target3
            bot_target_vline := line.new(p5_idx, p5_price, p5_idx, bot_target_price, color=bot_pattern_color, width=1, style=line.style_dotted)
            
            string lbl_sz = get_label_size()
            bot_label5 := label.new(p5_idx, p5_price, "5", color=color.new(color.white, 100), style=label.style_label_down, textcolor=i_bottom_text_color, size=lbl_sz)
            
            if i_show_info_table
                if not na(info_table)
                    table.delete(info_table)
                info_table := table.new(get_table_position(), 2, 6, border_width=2, border_color=bot_pattern_color, frame_width=2, frame_color=bot_pattern_color)
                string quality_grade = (bot_quality_score >= 85) ? get_text("excellent") : (bot_quality_score >= 75) ? get_text("very_good") : (bot_quality_score >= 65) ? get_text("good") : get_text("acceptable")
                string txt_size = get_text_size()
                table.cell(info_table, 0, 0, get_text("smart_double_bottom"), bgcolor=color.new(bot_pattern_color, 10), text_color=color.white, text_size=txt_size, text_halign=text.align_center)
                table.merge_cells(info_table, 0, 0, 1, 0)
                int row = 1
                table.cell(info_table, 0, row, get_text("quality_score"), bgcolor=color.new(bot_pattern_color, 80), text_color=color.white, text_size=txt_size, text_halign=text.align_left)
                table.cell(info_table, 1, row, str.tostring(bot_quality_score, "#.#") + "/100", bgcolor=color.new(bot_pattern_color, 90), text_color=bot_pattern_color, text_size=txt_size, text_halign=text.align_right)
                row += 1
                table.cell(info_table, 0, row, get_text("grade"), bgcolor=color.new(bot_pattern_color, 80), text_color=color.white, text_size=txt_size, text_halign=text.align_left)
                table.cell(info_table, 1, row, quality_grade, bgcolor=color.new(bot_pattern_color, 90), text_color=bot_pattern_color, text_size=txt_size, text_halign=text.align_right)
                row += 1
                table.cell(info_table, 0, row, get_text("target_mode"), bgcolor=color.new(bot_pattern_color, 85), text_color=color.white, text_size=txt_size, text_halign=text.align_left)
                table.cell(info_table, 1, row, mode_to_text(i_bottom_target_bullish), bgcolor=color.new(bot_pattern_color, 95), text_color=bot_pattern_color, text_size=txt_size, text_halign=text.align_right)
                row += 1
                table.cell(info_table, 0, row, get_text("target_price"), bgcolor=color.new(bot_pattern_color, 80), text_color=color.white, text_size=txt_size, text_halign=text.align_left)
                table.cell(info_table, 1, row, str.tostring(bot_target_price, format.mintick), bgcolor=color.new(bot_pattern_color, 90), text_color=bot_pattern_color, text_size=txt_size, text_halign=text.align_right)
                row += 1
                table.cell(info_table, 0, row, get_text("status"), bgcolor=color.new(bot_pattern_color, 80), text_color=color.white, text_size=txt_size, text_halign=text.align_left)
                table.cell(info_table, 1, row, get_text("bullish_breakout"), bgcolor=color.new(bot_pattern_color, 90), text_color=bot_pattern_color, text_size=txt_size, text_halign=text.align_right)

// رسم أهداف القاع المزدوج
if i_enable_double_bottom and bot_bearish_break and not na(bot_bearish_target) and not na(bot_bearish_bar)
    if not bot_bearish_achieved and low <= bot_bearish_target
        bot_bearish_achieved := true
        bot_bearish_achieved_bar := bar_index
    
    if not na(bot_bearish_hline)
        line.delete(bot_bearish_hline)
    if not na(bot_bearish_label)
        label.delete(bot_bearish_label)
    
    color current_color = bot_bearish_achieved ? i_target_achieved_color : i_bearish_reversal_color
    int end_bar = bot_bearish_achieved ? bot_bearish_achieved_bar : bar_index
    int bars_diff = end_bar - bot_bearish_bar
    
    if bars_diff >= 0 and bars_diff <= 500
        bot_bearish_hline := line.new(bot_bearish_bar, bot_bearish_target, end_bar, bot_bearish_target, color=current_color, width=1, style=line.style_dotted)
        string lbl_sz = get_label_size()
        string label_text = bot_bearish_achieved ? ("✓ " + get_text("target_down")) : get_text("target_down")
        bot_bearish_label := label.new(end_bar, bot_bearish_target, label_text, color=current_color, style=label.style_label_up, textcolor=color.white, size=lbl_sz)

if i_enable_double_bottom and bot_breakout and not na(bot_target_price) and not na(bot_breakout_bar)
    if not bot_target_achieved and high >= bot_target_price
        bot_target_achieved := true
        bot_target_achieved_bar := bar_index
    
    if not na(bot_target_hline)
        line.delete(bot_target_hline)
    if not na(bot_target_label)
        label.delete(bot_target_label)
    
    color current_color = bot_target_achieved ? i_target_achieved_color : bot_pattern_color
    int end_bar = bot_target_achieved ? bot_target_achieved_bar : bar_index
    int bars_diff = end_bar - bot_breakout_bar
    
    if bars_diff >= 0 and bars_diff <= 500
        bot_target_hline := line.new(bot_breakout_bar, bot_target_price, end_bar, bot_target_price, color=current_color, width=1, style=line.style_dotted)
        string lbl_sz = get_label_size()
        string label_text = bot_target_achieved ? ("✓ " + get_text("target")) : get_text("target")
        bot_target_label := label.new(end_bar, bot_target_price, label_text, color=current_color, style=label.style_label_down, textcolor=color.white, size=lbl_sz)

// ═══════════════════════════════════════════════════════════════════
// 📌 كشف القمة المزدوجة
// ═══════════════════════════════════════════════════════════════════

if i_enable_double_top
    ph = ta.pivothigh(high, left_len, right_len)
    
    if not na(ph)
        p4_price = ph
        p4_idx = bar_index - right_len
        array.push(highs_price, p4_price)
        array.push(highs_idx, p4_idx)
        if array.size(highs_price) > 50
            array.shift(highs_price)
            array.shift(highs_idx)
        
        int size = array.size(highs_price)
        if size >= 2
            for i = size - 2 to 0
                p2_price = array.get(highs_price, i)
                p2_idx = array.get(highs_idx, i)
                dist = p4_idx - p2_idx
                diff = math.abs(p2_price - p4_price)
                match_pct = (diff / math.max(p4_price, p2_price)) * 100
                
                if dist >= min_distance and match_pct <= tolerance_pct
                    lowest_l = 999999.0
                    p3_idx = -1
                    broken_high = false
                    
                    for k = 1 to (dist - 1)
                        check_idx = p4_idx - k
                        offset = bar_index - check_idx
                        val_low = low[offset]
                        val_high = high[offset]
                        if val_low < lowest_l
                            lowest_l := val_low
                            p3_idx := check_idx
                        max_tops = math.max(p2_price, p4_price)
                        if val_high > max_tops
                            broken_high := true
                    
                    p3_price = lowest_l
                    
                    if not broken_high and p3_price < p2_price and p3_price < p4_price
                        distance_2_3 = p3_idx - p2_idx
                        distance_3_4 = p4_idx - p3_idx
                        
                        if distance_2_3 >= min_arm_len and distance_3_4 >= min_arm_len
                            p1_price_best = 999999.0
                            p1_idx_best = -1
                            found_trend = false
                            
                            for t = min_trend_len to trend_lookback
                                idx_check = p2_idx - t
                                offset_check = bar_index - idx_check
                                if offset_check >= 0 and offset_check <= 5000
                                    val_l = low[offset_check]
                                    if val_l < p3_price and val_l < p1_price_best
                                        p1_price_best := val_l
                                        p1_idx_best := idx_check
                                        found_trend := true
                            
                            if found_trend
                                p1_price = p1_price_best
                                p1_idx = p1_idx_best
                                is_p2_highest = true
                                
                                for check_idx = p1_idx + 1 to p2_idx - 1
                                    current_offset = bar_index - check_idx
                                    if current_offset <= 5000 and high[current_offset] > p2_price
                                        is_p2_highest := false
                                        break
                                
                                if is_p2_highest
                                    bool pass_atr = true
                                    if i_use_atr_filter
                                        float current_atr = atr_value
                                        float avg_atr = ta.sma(atr_value, 50)
                                        if current_atr > avg_atr * 1.8
                                            pass_atr := false
                                    
                                    bool pass_adx = true
                                    if i_use_adx_filter
                                        if adx_value < (i_adx_threshold * 0.7)
                                            pass_adx := false
                                    
                                    float quality_score = calculate_top_quality(p1_price, p2_price, p3_price, p4_price, p2_idx, p4_idx)
                                    bool pass_quality = (quality_score >= i_min_quality)
                                    
                                    if pass_atr and pass_adx and pass_quality
                                        if not i_show_old_patterns
                                            if not na(top_neckline_left)
                                                line.delete(top_neckline_left)
                                            if not na(top_neckline_right)
                                                line.delete(top_neckline_right)
                                            if not na(top_l12)
                                                line.delete(top_l12)
                                            if not na(top_l23)
                                                line.delete(top_l23)
                                            if not na(top_l34)
                                                line.delete(top_l34)
                                            if not na(top_l45)
                                                line.delete(top_l45)
                                            if not na(top_fill_left)
                                                linefill.delete(top_fill_left)
                                            if not na(top_fill_23)
                                                linefill.delete(top_fill_23)
                                            if not na(top_fill_34)
                                                linefill.delete(top_fill_34)
                                            if not na(top_fill_45)
                                                linefill.delete(top_fill_45)
                                            if not na(top_label1)
                                                label.delete(top_label1)
                                            if not na(top_label2)
                                                label.delete(top_label2)
                                            if not na(top_label3)
                                                label.delete(top_label3)
                                            if not na(top_label4)
                                                label.delete(top_label4)
                                            if not na(top_label5)
                                                label.delete(top_label5)
                                            if not na(top_labelX)
                                                label.delete(top_labelX)
                                            if not na(top_target_vline)
                                                line.delete(top_target_vline)
                                            if not na(top_target_hline)
                                                line.delete(top_target_hline)
                                            if not na(top_target_label)
                                                label.delete(top_target_label)
                                            if not na(top_bullish_vline)
                                                line.delete(top_bullish_vline)
                                            if not na(top_bullish_hline)
                                                line.delete(top_bullish_hline)
                                            if not na(top_bullish_label)
                                                label.delete(top_bullish_label)
                                        
                                        color pattern_color = get_top_quality_color(quality_score)
                                        color fill_color = color.new(pattern_color, i_fill_transparency)
                                        string lbl_sz = get_label_size()
                                        
                                        top_l12 := line.new(p1_idx, p1_price, p2_idx, p2_price, color=pattern_color, width=2, style=line.style_solid)
                                        top_l23 := line.new(p2_idx, p2_price, p3_idx, p3_price, color=pattern_color, width=2, style=line.style_solid)
                                        top_l34 := line.new(p3_idx, p3_price, p4_idx, p4_price, color=pattern_color, width=2, style=line.style_solid)
                                        
                                        float slope = (p2_price - p1_price) / (p2_idx - p1_idx)
                                        float neckline_left_price = p3_price
                                        int neckline_left_idx = math.round(p1_idx + ((neckline_left_price - p1_price) / slope))
                                        top_neckline_left := line.new(neckline_left_idx, p3_price, p3_idx, p3_price, color=pattern_color, width=1, style=line.style_dotted)
                                        
                                        top_pattern_width := p4_idx - p2_idx
                                        top_max_wait_bars := math.round(top_pattern_width * i_extension_multiplier)
                                        top_pattern_start_bar := p4_idx
                                        int initial_end = math.min(bar_index, p4_idx + top_max_wait_bars)
                                        top_neckline_right := line.new(p3_idx, p3_price, initial_end, p3_price, color=pattern_color, width=1, style=line.style_dotted)
                                        
                                        roof_left = line.new(neckline_left_idx, p3_price, p2_idx, p3_price, color=color.new(color.white, 100))
                                        top_fill_left := linefill.new(top_l12, roof_left, color=fill_color)
                                        roof_23 = line.new(p2_idx, p3_price, p3_idx, p3_price, color=color.new(color.white, 100))
                                        top_fill_23 := linefill.new(top_l23, roof_23, color=fill_color)
                                        roof_34 = line.new(p3_idx, p3_price, p4_idx, p3_price, color=color.new(color.white, 100))
                                        top_fill_34 := linefill.new(top_l34, roof_34, color=fill_color)
                                        
                                        top_label1 := label.new(p1_idx, p1_price, "1", color=color.new(color.white, 100), style=label.style_label_up, textcolor=i_top_text_color, size=lbl_sz)
                                        top_label2 := label.new(p2_idx, p2_price, get_text("top1"), color=i_top_bg_color, style=label.style_label_down, textcolor=i_top_text_color, size=lbl_sz)
                                        top_label3 := label.new(p3_idx, p3_price, "3", color=color.new(color.white, 100), style=label.style_label_up, textcolor=i_top_text_color, size=lbl_sz)
                                        top_label4 := label.new(p4_idx, p4_price, get_text("top2"), color=i_top_bg_color, style=label.style_label_down, textcolor=i_top_text_color, size=lbl_sz)
                                        
                                        top_p1_price := p1_price
                                        top_p1_idx := p1_idx
                                        top_p2_price := p2_price
                                        top_p2_idx := p2_idx
                                        top_p3_price := p3_price
                                        top_p3_idx := p3_idx
                                        top_p4_price := p4_price
                                        top_p4_idx := p4_idx
                                        top_quality_score := quality_score
                                        top_pattern_color := pattern_color
                                        top_breakdown := false
                                        top_target_achieved := false
                                        top_invalidated := false
                                        top_bullish_break := false
                                        top_bullish_achieved := false
                                        top_bullish_bar := na
                                        top_bullish_target := na
                                        top_bullish_achieved_bar := na
                                        break

// تحديث القمة المزدوجة
if i_enable_double_top and not na(top_p3_price)
    if not top_bullish_break and not top_breakdown and not top_invalidated
        float max_top = math.max(top_p2_price, top_p4_price)
        if close > max_top
            top_bullish_break := true
            top_bullish_bar := bar_index
            
            if not na(top_l12)
                line.set_color(top_l12, i_bullish_reversal_color)
            if not na(top_l23)
                line.set_color(top_l23, i_bullish_reversal_color)
            if not na(top_l34)
                line.set_color(top_l34, i_bullish_reversal_color)
            if not na(top_neckline_left)
                line.set_color(top_neckline_left, i_bullish_reversal_color)
            if not na(top_neckline_right)
                line.delete(top_neckline_right)
            top_neckline_right := line.new(top_p3_idx, top_p3_price, bar_index, top_p3_price, color=i_bullish_reversal_color, width=1, style=line.style_dotted)
            
            [bt1, bt2, bt3] = calculate_top_bullish_targets(top_p2_price, top_p3_price, top_p4_price)
            top_bullish_target := i_top_target_bullish == "محافظ | Conservative" ? bt1 : i_top_target_bullish == "متوازن | Balanced" ? bt2 : bt3
            
            string lbl_sz = get_label_size()
            top_labelX := label.new(bar_index, close, "✖", color=color.new(color.white, 100), style=label.style_label_down, textcolor=i_bullish_reversal_color, size=lbl_sz)
            top_bullish_vline := line.new(bar_index, close, bar_index, top_bullish_target, color=i_bullish_reversal_color, width=1, style=line.style_dotted)
            
            if i_show_info_table
                if not na(info_table)
                    table.delete(info_table)
                info_table := table.new(get_table_position(), 2, 5, border_width=2, border_color=i_bullish_reversal_color, frame_width=2, frame_color=i_bullish_reversal_color)
                string txt_size = get_text_size()
                table.cell(info_table, 0, 0, get_text("top_failed"), bgcolor=color.new(i_bullish_reversal_color, 10), text_color=color.white, text_size=txt_size, text_halign=text.align_center)
                table.merge_cells(info_table, 0, 0, 1, 0)
                int row = 1
                table.cell(info_table, 0, row, get_text("target_price"), bgcolor=color.new(i_bullish_reversal_color, 80), text_color=color.white, text_size=txt_size, text_halign=text.align_left)
                table.cell(info_table, 1, row, str.tostring(top_bullish_target, format.mintick), bgcolor=color.new(i_bullish_reversal_color, 90), text_color=i_bullish_reversal_color, text_size=txt_size, text_halign=text.align_right)
                row += 1
                table.cell(info_table, 0, row, get_text("target_mode"), bgcolor=color.new(i_bullish_reversal_color, 85), text_color=color.white, text_size=txt_size, text_halign=text.align_left)
                table.cell(info_table, 1, row, mode_to_text(i_top_target_bullish), bgcolor=color.new(i_bullish_reversal_color, 95), text_color=i_bullish_reversal_color, text_size=txt_size, text_halign=text.align_right)
                row += 1
                table.cell(info_table, 0, row, get_text("status"), bgcolor=color.new(i_bullish_reversal_color, 80), text_color=color.white, text_size=txt_size, text_halign=text.align_left)
                table.cell(info_table, 1, row, get_text("reversal_upward"), bgcolor=color.new(i_bullish_reversal_color, 90), text_color=i_bullish_reversal_color, text_size=txt_size, text_halign=text.align_right)
    
    else if not top_bullish_break and not top_breakdown and not top_invalidated
        if (bar_index - top_pattern_start_bar) >= top_max_wait_bars
            top_invalidated := true
            if not na(top_neckline_right)
                line.delete(top_neckline_right)
            top_neckline_right := line.new(top_p3_idx, top_p3_price, top_pattern_start_bar + top_max_wait_bars, top_p3_price, color=color.new(top_pattern_color, 50), width=1, style=line.style_dotted)
        else
            if not na(top_neckline_right)
                line.delete(top_neckline_right)
            int current_end = math.min(bar_index, top_pattern_start_bar + top_max_wait_bars)
            top_neckline_right := line.new(top_p3_idx, top_p3_price, current_end, top_p3_price, color=top_pattern_color, width=1, style=line.style_dotted)
    
    if not top_bullish_break and not top_breakdown and not top_invalidated
        if close < top_p3_price
            top_breakdown := true
            top_breakdown_bar := bar_index
            int p5_idx = bar_index
            float p5_price = top_p3_price
            
            if not na(top_neckline_right)
                line.delete(top_neckline_right)
            top_neckline_right := line.new(top_p3_idx, top_p3_price, p5_idx, top_p3_price, color=top_pattern_color, width=1, style=line.style_dotted)
            
            top_l45 := line.new(top_p4_idx, top_p4_price, p5_idx, p5_price, color=top_pattern_color, width=2, style=line.style_solid)
            roof_45 = line.new(top_p4_idx, top_p3_price, p5_idx, top_p3_price, color=color.new(color.white, 100))
            top_fill_45 := linefill.new(top_l45, roof_45, color=color.new(top_pattern_color, i_fill_transparency))
            
            [target1, target2, target3] = calculate_top_bearish_targets(top_p3_price, top_p4_price, top_quality_score)
            top_target_price := i_top_target_bearish == "محافظ | Conservative" ? target1 : i_top_target_bearish == "متوازن | Balanced" ? target2 : target3
            top_target_vline := line.new(p5_idx, p5_price, p5_idx, top_target_price, color=top_pattern_color, width=1, style=line.style_dotted)
            
            string lbl_sz = get_label_size()
            top_label5 := label.new(p5_idx, p5_price, "5", color=color.new(color.white, 100), style=label.style_label_up, textcolor=i_top_text_color, size=lbl_sz)
            
            if i_show_info_table
                if not na(info_table)
                    table.delete(info_table)
                info_table := table.new(get_table_position(), 2, 6, border_width=2, border_color=top_pattern_color, frame_width=2, frame_color=top_pattern_color)
                string quality_grade = (top_quality_score >= 85) ? get_text("excellent") : (top_quality_score >= 75) ? get_text("very_good") : (top_quality_score >= 65) ? get_text("good") : get_text("acceptable")
                string txt_size = get_text_size()
                table.cell(info_table, 0, 0, get_text("smart_double_top"), bgcolor=color.new(top_pattern_color, 10), text_color=color.white, text_size=txt_size, text_halign=text.align_center)
                table.merge_cells(info_table, 0, 0, 1, 0)
                int row = 1
                table.cell(info_table, 0, row, get_text("quality_score"), bgcolor=color.new(top_pattern_color, 80), text_color=color.white, text_size=txt_size, text_halign=text.align_left)
                table.cell(info_table, 1, row, str.tostring(top_quality_score, "#.#") + "/100", bgcolor=color.new(top_pattern_color, 90), text_color=top_pattern_color, text_size=txt_size, text_halign=text.align_right)
                row += 1
                table.cell(info_table, 0, row, get_text("grade"), bgcolor=color.new(top_pattern_color, 80), text_color=color.white, text_size=txt_size, text_halign=text.align_left)
                table.cell(info_table, 1, row, quality_grade, bgcolor=color.new(top_pattern_color, 90), text_color=top_pattern_color, text_size=txt_size, text_halign=text.align_right)
                row += 1
                table.cell(info_table, 0, row, get_text("target_mode"), bgcolor=color.new(top_pattern_color, 85), text_color=color.white, text_size=txt_size, text_halign=text.align_left)
                table.cell(info_table, 1, row, mode_to_text(i_top_target_bearish), bgcolor=color.new(top_pattern_color, 95), text_color=top_pattern_color, text_size=txt_size, text_halign=text.align_right)
                row += 1
                table.cell(info_table, 0, row, get_text("target_price"), bgcolor=color.new(top_pattern_color, 80), text_color=color.white, text_size=txt_size, text_halign=text.align_left)
                table.cell(info_table, 1, row, str.tostring(top_target_price, format.mintick), bgcolor=color.new(top_pattern_color, 90), text_color=top_pattern_color, text_size=txt_size, text_halign=text.align_right)
                row += 1
                table.cell(info_table, 0, row, get_text("status"), bgcolor=color.new(top_pattern_color, 80), text_color=color.white, text_size=txt_size, text_halign=text.align_left)
                table.cell(info_table, 1, row, get_text("bearish_breakout"), bgcolor=color.new(top_pattern_color, 90), text_color=top_pattern_color, text_size=txt_size, text_halign=text.align_right)

// رسم أهداف القمة المزدوجة
if i_enable_double_top and top_bullish_break and not na(top_bullish_target) and not na(top_bullish_bar)
    if not top_bullish_achieved and high >= top_bullish_target
        top_bullish_achieved := true
        top_bullish_achieved_bar := bar_index
    
    if not na(top_bullish_hline)
        line.delete(top_bullish_hline)
    if not na(top_bullish_label)
        label.delete(top_bullish_label)
    
    color current_color = top_bullish_achieved ? i_target_achieved_color : i_bullish_reversal_color
    int end_bar = top_bullish_achieved ? top_bullish_achieved_bar : bar_index
    int bars_diff = end_bar - top_bullish_bar
    
    if bars_diff >= 0 and bars_diff <= 500
        top_bullish_hline := line.new(top_bullish_bar, top_bullish_target, end_bar, top_bullish_target, color=current_color, width=1, style=line.style_dotted)
        string lbl_sz = get_label_size()
        string label_text = top_bullish_achieved ? ("✓ " + get_text("target_up")) : get_text("target_up")
        top_bullish_label := label.new(end_bar, top_bullish_target, label_text, color=current_color, style=label.style_label_down, textcolor=color.white, size=lbl_sz)

if i_enable_double_top and top_breakdown and not na(top_target_price) and not na(top_breakdown_bar)
    if not top_target_achieved and low <= top_target_price
        top_target_achieved := true
        top_target_achieved_bar := bar_index
    
    if not na(top_target_hline)
        line.delete(top_target_hline)
    if not na(top_target_label)
        label.delete(top_target_label)
    
    color current_color = top_target_achieved ? i_target_achieved_color : top_pattern_color
    int end_bar = top_target_achieved ? top_target_achieved_bar : bar_index
    int bars_diff = end_bar - top_breakdown_bar
    
    if bars_diff >= 0 and bars_diff <= 500
        top_target_hline := line.new(top_breakdown_bar, top_target_price, end_bar, top_target_price, color=current_color, width=1, style=line.style_dotted)
        string lbl_sz = get_label_size()
        string label_text = top_target_achieved ? ("✓ " + get_text("target")) : get_text("target")
        top_target_label := label.new(end_bar, top_target_price, label_text, color=current_color, style=label.style_label_up, textcolor=color.white, size=lbl_sz)

// ═══════════════════════════════════════════════════════════════════
// 📌 التنبيهات
// ═══════════════════════════════════════════════════════════════════

alertcondition(bot_breakout, title="قاع - اختراق صاعد | Bottom Bullish", message="اختراق القاع المزدوج - صاعد!")
alertcondition(bot_target_achieved, title="قاع - تحقق هدف صاعد | Bottom Target", message="تحقق هدف القاع الصاعد!")
alertcondition(bot_bearish_break, title="قاع - فشل هبوطي | Bottom Failed", message="فشل القاع - هبوطي!")
alertcondition(bot_bearish_achieved, title="قاع - تحقق هدف هبوطي | Bottom Bearish Target", message="تحقق هدف القاع الهبوطي!")

alertcondition(top_breakdown, title="قمة - كسر هبوطي | Top Bearish", message="كسر القمة المزدوجة - هبوطي!")
alertcondition(top_target_achieved, title="قمة - تحقق هدف هبوطي | Top Target", message="تحقق هدف القمة الهبوطي!")
alertcondition(top_bullish_break, title="قمة - فشل صاعد | Top Failed", message="فشل القمة - صاعد!")
alertcondition(top_bullish_achieved, title="قمة - تحقق هدف صاعد | Top Bullish Target", message="تحقق هدف القمة الصاعد!")